/*
 * AbstractTableModel.java  0.4.0 / Oct 25, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
package com.cute4j.swing.table;

import java.util.EventListener;

import com.cute4j.core.events.EventListenerList;
import com.cute4j.swing.events.TableModelEvent;
import com.cute4j.swing.events.TableModelListener;


/**
 * Abstract Table Model.
 *
 * @author Slobodan Vrkacevic
 * @version 0.4.0
 */
public abstract class AbstractTableModel implements TableModel {

// Protected Fields. -----------------------------------------------------------

  protected EventListenerList listenerList;

// Public Constructors. --------------------------------------------------------

  /**
   * Constructs new AbstractTableModel object.
   */
  public AbstractTableModel() {
    listenerList = new EventListenerList();
  }

// Public Methods. -------------------------------------------------------------

  /**
   * Return the index of the specified column, or <tt>-1</tt> if there is no
   * such column.
   *
   * @param columnName the name of the column
   *
   * @return the index of the specified column
   */
  public int findColumn(String columnName) {
    int columnCount = getColumnCount();
    for (int index = 0; index < columnCount; index++) {
      String name = getColumnName(index);
      if (columnName.equals(name)) {
        return index;
      }
    }
    return -1;
  }

  /**
   * Fires table changed event.
   *
   * @param e the event to send
   */
  public void fireTableChanged(TableModelEvent e) {
    int count = listenerList.getListenerCount(TableModelListener.class);
    if (count > 0) {
      TableModelListener[] listeners = getTableModelListeners();
      for (int i = count - 1; i >= 0; i--) {
        listeners[i].tableChanged(e);
      }
    }
  }

  /**
   * Notifies listeners that table model has changed.
   */
  public void fireTableDataChanged() {
    fireTableChanged(new TableModelEvent(this, 0, Integer.MAX_VALUE));
  }

  /**
   * Notifies listeners that table structure has changed.
   */
  public void fireTableStructureChanged() {
    fireTableChanged(new TableModelEvent(this, TableModelEvent.HEADER_ROW));
  }

  /**
   * Fires table rows inserted event.
   *
   * @param firstRow the first row
   * @param lastRow the last row
   */
  public void fireTableRowsInserted(int firstRow, int lastRow) {
    fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
                                         TableModelEvent.ALL_COLUMNS,
                                         TableModelEvent.INSERT));
  }

  /**
   * Fires table rows updated event.
   *
   * @param firstRow the first row
   * @param lastRow the last row
   */
  public void fireTableRowsUpdated(int firstRow, int lastRow) {
    fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
                                         TableModelEvent.ALL_COLUMNS,
                                         TableModelEvent.UPDATE));
  }

  /**
   * Fires table rows deleted event.
   *
   * @param firstRow the first row
   * @param lastRow the last row
   */
  public void fireTableRowsDeleted(int firstRow, int lastRow) {
    fireTableChanged(new TableModelEvent(this, firstRow, lastRow,
                                         TableModelEvent.ALL_COLUMNS,
                                         TableModelEvent.DELETE));
  }

  /**
   * Fires table cell updated event.
   *
   * @param row the row
   * @param column the column
   */
  public void fireTableCellUpdated(int row, int column) {
    fireTableChanged(new TableModelEvent(this, row, row, column,
                                         TableModelEvent.UPDATE));
  }

  /**
   * Returns table model listeners.
   *
   * @return table model listeners
   */
  public TableModelListener[] getTableModelListeners() {
    int count = listenerList.getListenerCount(TableModelListener.class);
    TableModelListener[] listeners = new TableModelListener[count];
    if (count > 0) {
      System.arraycopy(listenerList.getListenersArray(TableModelListener.class),
                       0, listeners,  0, count);
    }
    return listeners;
  }

  /**
   * Returns listeners specified by the listener class.
   *
   * @param listenerClass the listener class
   *
   * @return listeners specified by the listener class
   */
  public EventListener[] getListeners(Class listenerClass) {
    return listenerList.getListeners(listenerClass);
  }

// TableModel Implementation. --------------------------------------------------

  /**
   * {@inheritDoc}
   */
  public String getColumnName(int columnIndex) { // NOPMD
    StringBuffer sb = new StringBuffer();
    while (columnIndex >= 0) {
      sb.insert(0, (char)('A' + (columnIndex % 26)));
      columnIndex = (columnIndex / 26) - 1;
    }
    return sb.toString();
  }

  /**
   * {@inheritDoc}
   */
  public Class getColumnClass(int columnIndex) {
    return Object.class;
  }

  /**
   * {@inheritDoc}
   */
  public boolean isCellEditable(int rowIndex, int columnIndex) {
    return false;
  }

  /**
   * {@inheritDoc}
   */
  public void setValueAt(Object value, int rowIndex, int columnIndex) {
    // empty method
  }

  /**
   * {@inheritDoc}
   */
  public void addTableModelListener(TableModelListener listener) {
    listenerList.add(TableModelListener.class, listener);
  }

  /**
   * {@inheritDoc}
   */
  public void removeTableModelListener(TableModelListener listener) {
    listenerList.remove(TableModelListener.class, listener);
  }

}
